use serde::{de::DeserializeOwned, Deserialize, Serialize};
use sqlx::{query, PgExecutor, Result};

use crate::filter;

pub mod aggregation;
pub mod url;
pub mod url_log;
pub mod user;
pub mod user_url;
pub mod user_url_log;

async fn del<'a>(e: impl PgExecutor<'a>, table: &str, id: &str) -> Result<u64> {
    let sql = format!("DELETE FROM {table} WHERE id=$1");
    let q = query(&sql).bind(id);
    let aff = q.execute(e).await?.rows_affected();
    Ok(aff)
}

#[derive(Serialize, Deserialize)]
pub struct Pagination<T> {
    pub page: u32,
    pub page_size: u32,
    pub total_page: u32,
    pub total: u32,
    pub data: Vec<T>,
}

impl<T: DeserializeOwned + Serialize> Pagination<T> {
    pub fn new(total: u32, page: u32, page_size: u32, data: Vec<T>) -> Self {
        let total_page = f64::ceil(total as f64 / page_size as f64) as u32;

        Self {
            page,
            page_size,
            total_page,
            total,
            data,
        }
    }

    pub fn quick(total: u32, p: &filter::Pagination, data: Vec<T>) -> Self {
        Self::new(total, p.page, p.page_size, data)
    }
}
